define(function(){

    var test = !1;
    var myDiagram;
    var search = View.search();
    var $$ = go.GraphObject.make;  // for more concise visual tree definitions
    var pathMap;
    var getUrl = test ? './json/order.json' : '';
    var mask = (function(){
        var $mask = $('<div id="mask">');
        var $body = $('body');
        $mask.html('<img src="./assets/img/loading.gif" />');
        return {
            open:function(){
                $body.append($mask);
            },
            close:function(){
                $mask.remove();
            }
        }
    }());
    //
    var Temp = function(name,group){
        var t = this;
        var res = t.data;
        var tempName = t.from || "default";
        if(!res){
            $.ajax({
                url:"./json/flow_style.json",
                async:false,
                success:function(result){
                    t.data = result;
                    res = result;
                }
            })
        }
        //
        if(group){
            name += tempName == "default" ? "" : "_"+ Temp.from;
            return res.group[group][name];
        }else{
            return res[tempName][name];
        }
    }
    // diagram - 初始化
    function init() {
        if(myDiagram==void 0){
            var config = {
                allowDrop: true,
                //"LinkDrawn": showLinkLabel,  // this DiagramEvent listener is defined below
                //"LinkRelinked": showLinkLabel,
                "rotatingTool.snapAngleMultiple": 90,
                "rotatingTool.snapAngleEpsilon": 45,
                "animationManager.isEnabled": false,
                "initialContentAlignment": go.Spot.Center,
                "undoManager.isEnabled": true,
                "allowZoom":true,
                "padding":new go.Margin(80,80),
                "scale":.6,
                "isReadOnly":true,
                //"layout":$$(go.TreeLayout, {
                //    angle: 0,
                //    arrangement: go.TreeLayout.ArrangementVertical,
                //    isRealtime: false,
                //    layerSpacing: 80,
                //    setsPortSpot: false,
                //    setsChildPortSpot: false
                //})
            }
            myDiagram = $$(go.Diagram, "myDiagramDiv",config);
            myDiagram.toolManager.linkingTool.temporaryLink.routing = go.Link.Orthogonal;
            myDiagram.toolManager.relinkingTool.temporaryLink.routing = go.Link.Orthogonal;
            //myDiagram.contextMenu = $$(go.HTMLInfo, {show: Dialog.showMenu,mainElement: Dialog.$contextMenu[0]});
            loop();
            //
            pathMap || (pathMap = getPathMap());
            window.myDiagram = myDiagram;
        }


        myDiagram.startTransaction();
        // diagram - 面板背景
        document.getElementById("myDiagramDiv").style.backgroundColor = Temp("bg");
        // diagram - 元素组件定义
        myDiagram.nodeTemplateMap.add("Process",
            $$(go.Node, "Spot",
                nodeStyle(),
                {
                    zOrder:99,
                    selectionAdorned: false,
                    resizable: false,
                    selectionObjectName: "ICON"
                },
                new go.Binding("zOrder","",function(row){
                    return row.odid ? 99 : 70;
                }),
                $$(go.Panel,"Auto",
                    {name:"ICON"},
                    $$(go.Shape, "RoundedRectangle",
                        {
                            strokeWidth:2,
                            stroke:'transparent',
                            minSize: new go.Size(180, 70),
                            shadowVisible:true
                        },
                        new go.Binding("fill","",function(row){
                            return row.odid ? Temp("bkButton",row.group) : "rgba(221,221,221,.2)"
                        })
                    ),
                    $$(go.TextBlock ,
                        {
                            alignment:go.Spot.LeftCenter,
                            margin:new go.Margin(8,10),
                            maxSize:new go.Size(160,NaN),
                            shadowVisible:false
                        },
                        textStyle(10,Temp("fontText")),
                        new go.Binding("text","text")
                    )
                ),
                makePort("T", "T", go.Spot.TopCenter, true, true),
                makePort("L", "L", go.Spot.LeftCenter, true, true),
                makePort("R", "R", go.Spot.RightCenter, true, true),
                makePort("B", "B", go.Spot.BottomCenter, true, true)
            ));

        myDiagram.nodeTemplateMap.add("ExclusiveGateway",
            $$(go.Node, "Spot", nodeStyle(),  // the whole node panel
                {
                    resizable: false,
                    selectionObjectName: "ICON"
                },
                $$(go.Panel,"Auto",
                    {name:"ICON"},
                    $$(go.Shape, "RoundedRectangle",
                        {
                            strokeWidth:2,
                            stroke:'transparent',
                            desiredSize: new go.Size(180, 70),
                            shadowVisible:true
                        },
                        new go.Binding("fill","",function(row){return Temp("bkButton",row.group)})
                    )
                ),
                $$(go.Panel, "Vertical",
                    {
                        alignment:new go.Spot(0.5,0,0,0)
                    },
                    $$(go.Panel,"Auto",
                        $$(go.Shape, "Circle",
                            {
                                shadowVisible:false,
                                desiredSize: new go.Size(60,60),
                                strokeWidth:4,
                                stroke:"white"
                            },
                            new go.Binding("fill","",function(row){return Temp("bkButton",row.group)})
                        ),
                        $$(go.Picture,Temp("imgExclusiveGateway"), {
                            desiredSize: new go.Size(30,30)
                        })
                    )
                ),
                $$(go.Panel,
                    $$(go.TextBlock ,
                        {
                            desiredSize: new go.Size(150,58),
                            margin:new go.Margin(65,0,0,0),
                            verticalAlignment:go.Spot.TopCenter,
                            textAlign:"center",
                            shadowVisible:false
                        },
                        textStyle(10,Temp("fontText")),
                        new go.Binding("text","text")
                    )
                ),
                makePort("T", "T", go.Spot.TopCenter, true, true),
                makePort("L", "L", go.Spot.LeftCenter, true, true),
                makePort("R", "R", go.Spot.RightCenter, true, true),
                makePort("B", "B", go.Spot.BottomCenter, true, true)
            ))

        myDiagram.nodeTemplateMap.add("ParallelGateway",
            $$(go.Node, "Spot", nodeStyle(),  // the whole node panel
                {
                    shadowVisible:false,
                    resizable: false,
                    selectionObjectName: "ICON"
                },
                $$(go.Panel,"Auto",
                    {name:"ICON"},
                    $$(go.Shape, "RoundedRectangle",
                        {
                            strokeWidth:2,
                            stroke:'transparent',
                            desiredSize: new go.Size(180, 70),
                            shadowVisible:true
                        },
                        new go.Binding("fill","",function(row){return Temp("bkButton",row.group)})
                    )
                ),
                $$(go.Panel, "Vertical",
                    {
                        alignment:new go.Spot(0.5,0,0,0)
                    },
                    $$(go.Panel,"Auto",
                        $$(go.Shape, "Circle",
                            {
                                desiredSize: new go.Size(60,60),
                                strokeWidth:4,
                                stroke:"white"
                            },
                            new go.Binding("fill","",function(row){return Temp("bkButton",row.group)})
                        ),
                        $$(go.Picture,Temp("imgParallelGateway"), {
                            desiredSize: new go.Size(30,30)
                        })
                    )
                ),
                $$(go.Panel,
                    $$(go.TextBlock ,
                        {
                            desiredSize: new go.Size(150,58),
                            margin:new go.Margin(65,0,0,0),
                            verticalAlignment:go.Spot.TopCenter,
                            textAlign:"center",
                            shadowVisible:false
                        },
                        textStyle(10,Temp("fontText")),
                        new go.Binding("text","text")
                    )
                ),
                makePort("T", "T", go.Spot.TopCenter, true, true),
                makePort("L", "L", go.Spot.LeftCenter, true, true),
                makePort("R", "R", go.Spot.RightCenter, true, true),
                makePort("B", "B", go.Spot.BottomCenter, true, true)
            ))

        myDiagram.nodeTemplateMap.add("Start",
            $$(go.Node, "Auto",
                nodeStyle(),
                {
                    selectionAdorned: false
                },
                $$(go.Panel,"Auto",
                    {
                        name: "BODY",
                        margin:6,
                        background:"transparent",
                        alignment: go.Spot.Center
                    },
                    $$(go.Shape,"RoundedRectangle",{
                            desiredSize: new go.Size(180, 60),
                            fill:Temp("bkBg","Start"),
                            strokeWidth:0
                        }
                    ),
                    $$(go.TextBlock,{
                        margin:10,
                        text:"开始",
                        font: "bold 14pt sans-serif",
                        stroke:"white"
                    })
                ),
                makePort("L", "L", go.Spot.LeftCenter, true, true),
                makePort("R", "R", go.Spot.RightCenter, true, true),
                makePort("B", "B", go.Spot.BottomCenter, true, true)
            ));

        myDiagram.nodeTemplateMap.add("End",
            $$(go.Node, "Auto",
                nodeStyle(),
                {
                    selectionAdorned: false
                },
                $$(go.Panel,"Auto",
                    {
                        name: "BODY",
                        margin:6,
                        background:"transparent",
                        alignment: go.Spot.Center
                    },
                    $$(go.Shape,"RoundedRectangle",{
                            desiredSize: new go.Size(180, 60),
                            fill:Temp("bkBg","End"),
                            strokeWidth:0
                        }
                    ),
                    $$(go.TextBlock,{
                        margin:10,
                        text:"结束",
                        font: "bold 14pt sans-serif",
                        stroke:"white"
                    })
                ),
                makePort("T", "T", go.Spot.TopCenter, true, true),
                makePort("L", "L", go.Spot.LeftCenter, true, true),
                makePort("R", "R", go.Spot.RightCenter, true, true)
            ));


        myDiagram.linkTemplate = $$(
            go.Link,
            {
                zOrder:80,
                isShadowed:true,
                shadowVisible:false,
                shadowOffset:new go.Point(2,3),
                shadowColor:"rgba(0,0,0,.1)",
                routing: go.Link.Orthogonal,
                curve: go.Link.JumpOver,
                adjusting: go.Link.Stretch,
                corner: 10,
                smoothness:0 ,// routing:Orthogonal  + curve:Bezier
                relinkableFrom: true,
                relinkableTo: true,
                reshapable: true,
                resegmentable: true,
                selectable: true,      // links be selected by the user
                //layerName: "Background",  // don't cross in front of any nodes
                toShortLength: 1
            },
            new go.Binding("points","points",function(v){
                return v.split(",").map(function(v){return Number(v);});
            }).makeTwoWay(function(point,node){
                var arr = [];
                point.iterator.each(function(o){
                    if(o.J){
                        arr.push(+Number(o.M).toFixed(4))
                        arr.push(+Number(o.N).toFixed(4))
                    }else{
                        arr.push(+Number(o.x).toFixed(4))
                        arr.push(+Number(o.y).toFixed(4))
                    }
                })
                return arr.join(",");
            }),
            new go.Binding("fromPort","fromPort").makeTwoWay(),
            new go.Binding("toPort","toPort").makeTwoWay(),
            $$(go.Shape, { isPanelMain: true, stroke:"rgba(210,210,210,.3)",strokeWidth: 9 }),
            $$(go.Shape, { isPanelMain: true, stroke:Temp("link"),strokeWidth: 8 }),
            $$(go.Shape,{
                isPanelMain: true,
                name: "PIPE",
                strokeWidth:8,
                stroke:"#fff",
                strokeDashArray:[5, 5]
            }),
            // occupy
            $$(go.Panel,"Auto",
                {},
                $$(go.Shape,"RoundedRectangle",
                    {
                        name: "OCCUPY_VISIBLE",
                        shadowVisible:true,
                        desiredSize: new go.Size(120,28),
                        parameter1: 14,
                        stroke:"rgba(220,220,220,.1)",
                        strokeWidth:2
                    },
                    new go.Binding("fill","",function(row){
                        return Temp("fontOccupyNo")[0];
                    }),
                    new go.Binding("visible","",function(row){
                        return !!row.transit;
                    })
                ),
                $$(go.Panel,"Vertical",
                    {
                        alignment:go.Spot.Center,
                        margin:new go.Margin(0,10)
                    },
                    $$(go.TextBlock, "transition",  // the label text
                        textStyle(9,Temp("fontOccupyNo")[1]),
                        {
                            name: "OCCUPY_VALUE",
                            margin:new go.Margin(0,0,0,0),
                            textAlign: "center"
                        },
                        new go.Binding("text","",function(row){
                            return row.transit?("在途时间: "+row.transit)+'s':'';
                        })
                    )
                )
            )
        );


        myDiagram.groupTemplate =
            $$(go.Group, "Auto",
                nodeStyle(),
                {
                    isShadowed:true,
                    shadowVisible:false,
                    shadowOffset:new go.Point(1,1),
                    shadowColor:"rgba(0,0,0,.1)",
                    selectionAdorned: false
                },
                new go.Binding("zOrder","",function(row){return Temp("zOrder",row.key) || 1;}),
                $$(go.Shape, "RoundedRectangle",
                    {
                        shadowVisible:true,
                        strokeWidth: 0,
                        spot1: go.Spot.TopLeft,
                        spot2: go.Spot.BottomRight
                    },
                    new go.Binding("fill","",function(row){return Temp("bkBg",row.key)}).makeTwoWay()
                ),
                $$(go.Panel,"Vertical",
                    {
                        stretch:go.GraphObject.Horizontal
                    },
                    $$(go.Panel,"Auto",
                        {
                            stretch:go.GraphObject.Horizontal,
                        },
                        $$(go.Shape, "RoundedTopRectangle",
                            {
                                stretch:go.GraphObject.Horizontal,
                                strokeWidth: 0,
                                height:50
                            },
                            new go.Binding("fill","",function(row){return Temp("bkTop",row.key)}).makeTwoWay()
                        ),
                        $$(go.Panel,"Horizontal",
                            {
                                alignment:go.Spot.LeftCenter
                            },
                            $$(go.Picture,
                                {
                                    width:20,
                                    height:20,
                                    margin:new go.Margin(5,5,5,20),
                                    alignment:go.Spot.LeftCenter
                                },
                                new go.Binding("source", "",function(row){
                                    return Temp("icon",row.key);
                                })
                            ),
                            $$(go.TextBlock,
                                {
                                    font: "normal 12pt Sans-Serif",
                                    stroke:"#fff",
                                    margin: new go.Margin(10, 10)
                                },
                                new go.Binding("text", "key")
                            )
                        )
                    ),
                    $$(go.Placeholder,
                        {
                            padding: new go.Margin(20,40)
                        }
                    )
                )
            );

        //
        myDiagram.commitTransaction();
        function showLinkLabel(e) {
            //var label = e.subject.findObject("LABEL");
            //if (label !== null) label.visible = (e.subject.fromNode.data.figure === "Diamond");
        }
        function nodeStyle() {
            return [
                new go.Binding("location", "pos", go.Point.parse).makeTwoWay(function(a){
                    return Math.ceil(a.x.toString())+" "+Math.ceil(a.y.toString())
                })
                //{locationSpot: go.Spot.Center}
            ];
        }
        function textStyle(size,stroke,bold) {
            return {
                wrap: go.TextBlock.OverflowClip,
                stroke: stroke || '',
                font: (bold||'normal ') + " " + (size || 11) + "pt Helvetica, Arial, sans-serif"
            }
        }
        function makePort(name, alignName, spot, output, input) {
            var horizontal = false;
            switch (alignName){
                case "T":{
                    horizontal = true;
                    align = new go.Spot(0.5, 0, 0, 5);
                }
                    break;
                case "B":{
                    horizontal = true;
                    align = new go.Spot(0.5, 1, 0, -5);
                }
                    break;
                case "R":
                    align = new go.Spot(1, 0.5, -5, 0);
                    break;
                case "L":
                    align = new go.Spot(0, 0.5, 5, 0);
                    break;
            }
            return $$(go.Shape,
                {
                    fill: "transparent",  // changed to a color in the mouseEnter event handler
                    strokeWidth: 0,  // no stroke
                    width: horizontal ? 60 : 8,  // if not stretching horizontally, just 8 wide
                    height: !horizontal ? 60 : 8,  // if not stretching vertically, just 8 tall
                    alignment: align,  // align the port on the main Shape
                    stretch: (horizontal ? go.GraphObject.Horizontal : go.GraphObject.Vertical),
                    portId: name,  // declare this object to be a "port"
                    fromSpot: spot,  // declare where links may connect at this port
                    fromLinkable: output,  // declare whether the user may draw links from here
                    toSpot: spot,  // declare where links may connect at this port
                    toLinkable: input,  // declare whether the user may draw links to here
                    cursor: "pointer",  // show a different cursor to indicate potential link point
                    mouseEnter: function(e, port) {  // the PORT argument will be this Shape
                        if (!e.diagram.isReadOnly) port.fill = "blue";
                    },
                    mouseLeave: function(e, port) {
                        port.fill = "transparent";
                    }
                });
        }
    };



    //  diagram - 业务函数
    function definePathPattern(geostr, color, width, cap) {
        if (typeof name !== 'string' || typeof geostr !== 'string') throw new Error("invalid name or geometry string argument: " + name + " " + geostr);
        if (color === undefined) color = "black";
        if (width === undefined) width = 1;
        if (cap === undefined) cap = "square";
        return go.GraphObject.make(go.Shape,
            {
                geometryString: geostr,
                fill: "transparent",
                stroke: color,
                strokeWidth: width,
                strokeCap: cap
            }
        );
    }
    function getPathMap(){
        // Define a bunch of small Shapes that can be used as values for Shape.pathPattern
        var PathPatterns = new go.Map('string', go.Shape);
        PathPatterns.add("Dot", definePathPattern("M0 0 M8 0 L8.1 0", "gray", 4, "round"));
        PathPatterns.add("Herringbone", definePathPattern("M0 0 L2 2 L0 4  M1.1 0.1 L2.1 2.1 L1.1 4.1 M10 0 L12 2 L10 4","white",1,"round"));
        PathPatterns.add("Sawtooth", definePathPattern("M0 3 L4 0 2 6 6 3"));
        //
        return function(name){
            return PathPatterns.getValue(name);
        }
    }
    function getPathDot(color){
        return definePathPattern("M0 0 M10 0 L20 0 M30 0",color || "gray", 8, "round");
    }


    function loop() {
        var diagram = myDiagram;
        var handerTime = 300;
        var hander;
        var start = function() {
            var oldskips = diagram.skipsUndoManager;
            diagram.startTransaction("start");
            diagram.skipsUndoManager = true;
            if(diagram.scale>0.25){
                for(var key in loop.funs){
                    loop.funs[key]();
                }
            }
            diagram.skipsUndoManager = oldskips;
            diagram.commitTransaction("start");
            clearTimeout(hander);
            hander = setTimeout(start,handerTime);
        }
        //
        hander || start();
    }
    loop.funs = {
        links:function(){
            myDiagram.links.each(function(link) {
                var shape = link.findObject("PIPE");
                if(shape){
                    var off = shape.strokeDashOffset - 4;
                    shape.strokeDashOffset = (off <= 0) ? 20 : off;
                }
            });
        },
        occupy:function(){
            if(!myDiagram.result){return;}
            myDiagram.links.each(function(node) {
                var one = node.data;
                var el = node && node.findObject("OCCUPY_VALUE");
                if(!el){
                    return;
                }
                //
                var style = Temp("fontOccupyNo");
                var box = node.findObject("OCCUPY_VISIBLE");
                if(one.transit_valid){
                    style[1]!=el.stroke || (style = Temp("fontOccupyCh"));
                }
                box.fill = style[0];
                el.stroke = style[1];
            })
        }
    }

    function loopLink(path){
        //var val = "F M0 2 M0 2 L4 2 L4 0 L8 4 L4 8 L4 6 L0 6z M20 2";
        var x_arr = [0,4,4,8,4,4,0];
        var arr;
        var str = path.geometryString;
        var offset = str.split(/\s/)[3].replace("M","");
        offset -= 5;
        offset < 0 && (offset = 15);
        arr = x_arr.map(function(v){
            return v + offset;
        });
        console.log(arr.toString());
        path.geometryString = "F M0 2 M"+arr[0]+" 2 L"+arr[1]+" 2 L"+arr[2]+" 0 L"+arr[3]+" 4 L"+arr[4]+" 8 L"+arr[5]+" 6 L"+arr[6]+" 6z M20 2";
    }


    function save(){
        var data = myDiagram.model.toJSON().replace("\"class\"","\"version\":\""+search.version+"\",\"class\"");//.replace("class","odid\":\"\",\"pos");
        mask.open();
        $.ajax({
            url:View.baseUrl + '/orderStep/pos',
            type:"put",
            contentType:"application/json",
            data:data,
            success:function(res){
                mask.close();
                if(res=="success"){
                    alert("OK");
                }
            },
            error:function(){
                mask.close();
                alert("ERROR");
            }
        })
    }


    function load() {
        var url = getUrl || View.baseUrl + "/order/step/query?" + $.param(search);
        mask.open();
        if(!/^v1/.test(search.version)){return;}
        $.getJSON(url,{},function(res){//'./json/data.json'  $.baseURI+"/neo4j/all"
            res.class = "go.GraphLinksModel";
            res.linkFromPortIdProperty =  "fromPort";
            res.linkToPortIdProperty = "toPort";
            mask.close();
            myDiagram.result = JSON.parse(JSON.stringify(res));
            myDiagram.model = go.Model.fromJson(res);
        })
    }

    function getOne(arr,match,flag){
        var one;
        arr.every(function(v,i){
            var isThis = true;
            for(var key in match){
                if(match[key]!=v[key]){
                    isThis = false;
                }
            }
            if(isThis){
                one = v;
                flag && (arr.splice(i,1));
            }
            return !isThis;
        });
        return one;
    }

    //
    $.baseURI = "http://172.16.6.235:8080"; // 172.16.6.235:8080";  //192.168.199.139:8080";
    $.API = {
        init:init,
        save:save,
        load:load,
        //
        theme:function(name){
            Temp.from = name;
            init();
        },
        make:function(res){
            if(res){
                res = localStorage.setItem("json");
                myDiagram.model = go.Model.fromJson(res);
            }else{
                res = myDiagram.model.toJSON();
                localStorage.setItem("json",res);
                return res;
            }
        }
    }
})